package com.cctc.juc.source.Bitc.Icontainer;

import java.util.*;
import java.util.concurrent.locks.ReentrantLock;

/**
 * [CopyOnWriteArrayList] 线程安全的 List。
 * [COW 写时复制思想] 在修改器对一块内存进行修改时，不直接在原内存上进行操作，而是将内存复制一份，在新内存中进行写操作，写完之后，再将原来的指针（或引用）指向新的内存，原来的内存被回收，即 [读原本、写副本、写完之后切换为副本，保证写不影响读，以提升读操作的并发性能]。
 * - CopyOnWriteArrayList 是 [COW 写时复制思想] 的一种典型实现案例；
 * - 类似的实现案例还有 MySQL 中基于 Undo Log 日志和虚拟表视图实现数据库事务 RC、RR 隔离级别的 MVCC 多版本并发控制机制。
 * CopyOnWriteArrayList 类内部实现原理：读的时候，不需要任何同步控制，因为原数组不会发生修改，只会被另外一个原数组副本替换，因此读操作是线程安全的；写的时候，需要加上独占锁，确保同一时刻只有一个线程进行写操作，避免多线程写的时候复制出多个副本，引发线程安全问题。
 * CopyOnWriteArrayList 与 ReentrantReadWriteLock 的比较：ReentrantReadWriteLock 为读读共享、写写互斥、读写互斥、写读互斥；而 CopyOnWriteArrayList 基于 COW 写时复制思想，为读读共享、写写互斥、读写隔离、写读隔离，即只有写写之间才需要加锁同步等待，将读取操作性能发挥到了极致。
 */
public class COWArrayList_AAAAA<E> implements List<E> {
    // --- [核心属性] --- //
    private transient volatile Object[] array;
    final transient ReentrantLock lock = new ReentrantLock();

    // --- [核心方法] --- //

    final Object[] getArray() {
        return array;
    }


    final void setArray(Object[] a) {
        array = a;
    }

    @Override
    public E get(int index) {
        /**
         * 读操作。
         * - 不需要任何同步控制，因为 array 不会发生修改，只会被另外一个 array 替换，因此本身是线程安全的。
         */
        return get(getArray(), index);
    }

    private E get(Object[] a, int index) {
        return (E) a[index];
    }

    @Override
    public boolean add(E e) {
        /**
         * 写操作。
         * - 写的时候需要加上独占锁，确保同一时刻只有一个线程进行写操作，避免多线程写的时候复制出多个副本，引发线程安全问题。
         */
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Object[] elements = getArray();
            int len = elements.length;
            // 1）复制一份副本
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            // 2）在副本上进行更新操作
            newElements[len] = e;
            // 3）指向副本
            setArray(newElements);
            return true;
        } finally {
            lock.unlock();
        }
    }

    // --- [其他方法] --- //

    @Override
    public int size() {
        return 0;
    }

    @Override
    public boolean isEmpty() {
        return false;
    }

    @Override
    public boolean contains(Object o) {
        return false;
    }

    @Override
    public Iterator<E> iterator() {
        return null;
    }

    @Override
    public Object[] toArray() {
        return new Object[0];
    }

    @Override
    public <T> T[] toArray(T[] a) {
        return null;
    }

    @Override
    public boolean remove(Object o) {
        return false;
    }

    @Override
    public boolean containsAll(Collection<?> c) {
        return false;
    }

    @Override
    public boolean addAll(Collection<? extends E> c) {
        return false;
    }

    @Override
    public boolean addAll(int index, Collection<? extends E> c) {
        return false;
    }

    @Override
    public boolean removeAll(Collection<?> c) {
        return false;
    }

    @Override
    public boolean retainAll(Collection<?> c) {
        return false;
    }

    @Override
    public void clear() {

    }

    @Override
    public E set(int index, E element) {
        return null;
    }

    @Override
    public void add(int index, E element) {

    }

    @Override
    public E remove(int index) {
        return null;
    }

    @Override
    public int indexOf(Object o) {
        return 0;
    }

    @Override
    public int lastIndexOf(Object o) {
        return 0;
    }

    @Override
    public ListIterator<E> listIterator() {
        return null;
    }

    @Override
    public ListIterator<E> listIterator(int index) {
        return null;
    }

    @Override
    public List<E> subList(int fromIndex, int toIndex) {
        return null;
    }
}
